package cn.xiaolang.function.java_jvm;

import lombok.AllArgsConstructor;
import lombok.Data;
import lombok.NoArgsConstructor;
import org.openjdk.jol.info.ClassLayout;
import org.openjdk.jol.vm.VM;

import java.io.IOException;

/**
 * PS1：不是说Klass是64bits(8个字节)但是这儿只有4个字节，因为默认情况下是开启压缩指针的，我们可以通过JVM运行参数-XX:-UseCompressedOops来关闭压缩指针，这样Klass就是8个字节了。
 * PS2：虚拟机在启动的时候对于偏向锁有延迟，即偏向锁功能要在JVM启动几秒后才会激活，所以要关闭偏向锁的延迟，在JVM启动参数添加 -XX:BiasedLockingStartupDelay=0
 * @author Dean
 * @date 2023/4/25
 */
public class MarkWordByJolSample {

    private static final PersonInfo perInfo = new PersonInfo("Dean");

    public static void main(String[] args) throws IOException {
        // =================如下依赖jol工具，maven依赖===================
        //打印JVM的详细信息
        // 不是说Klass是64bits(8个字节)但是这儿只有4个字节，因为默认情况下是开启压缩指针的，
        // 我们可以通过JVM运行参数-XX:-UseCompressedOops来关闭压缩指针，这样Klass就是8个字节了。

        System.out.println(VM.current().details());

        System.out.println("---加锁前---");
        System.out.println(ClassLayout.parseInstance(perInfo).toPrintable());

        sync();

        //打印对应的对象头信息
        System.out.println("---无锁---");
        System.out.println(ClassLayout.parseInstance(perInfo).toPrintable());
    }

    // 这时候大家会有疑问了，为什么在没有加锁之前是偏向锁，准确的说，应该是叫可偏向的状态，因为它后面没有存线程的ID，当lock ing的时候，后面存储的就是线程的ID（50276357）。这里我打印了当前线程的id，发现和对象头中存储的id不一样，实际上对象头中存储的是os的线程id，而不是Thread.currentThread.getId()得到的线程id，它是JVM分配的id，不是os的线程id。
    private static void sync() {
        synchronized (perInfo) {
            System.out.println("---thread id---" + Thread.currentThread().getId());
            System.out.println("---偏向锁---");
            System.out.println(ClassLayout.parseInstance(perInfo).toPrintable());
        }
    }

    @Data
    @AllArgsConstructor
    @NoArgsConstructor
    static class PersonInfo {
        String name;
    }
}